<?php

namespace pUtils;

class verify
{

    /**
     * @var mixed|string|null
     */
    public static mixed $input = "";
    /**
     * @var bool
     */
    public static bool $result = true;

    public function __construct($input = null, $result = true)
    {
        self::$input = $input;
        self::$result = $result;
    }

    /** 返回验证结果
     * @return bool
     */
    public static function run(): bool
    {
        return self::exec();
    }

    /** 返回验证结果
     * @return bool
     */
    public static function exec(): bool
    {
        $result = self::$result;

        self::$input = null;
        self::$result = true;

        return $result;
    }

    /** 验证是否为null或空字符串
     * @param mixed $input
     * @return verify
     */
    public static function isNull(mixed $input = null): verify
    {
        if (func_num_args() > 0) {
            self::$input = $input;
        }

        return new self(self::$input, self::$result && !!utils::isNull(self::$input));
    }

    /** 验证是否为null或空字串或空数组
     * @param mixed $input
     * @return verify
     */
    public static function isEmpty(mixed $input = null): verify
    {
        if (func_num_args() > 0) {
            self::$input = $input;
        }

        return new self(self::$input, self::$result && !!utils::isEmpty(self::$input));
    }

    /** 验证是否不为null和空字串
     * @param mixed $input
     * @return verify
     */
    public static function isNotNull(mixed $input = null): verify
    {
        if (func_num_args() > 0) {
            self::$input = $input;
        }

        return new self(self::$input, self::$result && !utils::isNull(self::$input));
    }

    /** 验证是否符合指定的日期格式
     * @param string|array|null $formats
     * @param mixed $input
     * @return verify
     */
    public static function isDate(string|array|null $formats = null, mixed $input = null): verify
    {
        if (func_num_args() > 1) {
            self::$input = $input;
        }

        return new self(self::$input, self::$result && !!utils::isDate(self::$input, $formats));
    }

    /** 验证是否为整数或整数字串
     * @param mixed $input
     * @return verify
     */
    public static function isInt(mixed $input = null): verify
    {
        if (func_num_args() > 0) {
            self::$input = $input;
        }

        return new self(self::$input, self::$result && !!utils::isInt(self::$input));
    }

    /** 验证是否为浮点数或浮点数字串
     * @param null $input
     * @return verify
     */
    public static function isFloat($input = null): verify
    {
        if (func_num_args() > 0) {
            self::$input = $input;
        }

        return new self(self::$input, self::$result && !!utils::isFloat(self::$input));
    }

    /** 验证是否为数值
     * @param null $input
     * @return verify
     */
    public static function isNumber($input = null): verify
    {
        if (func_num_args() > 0) {
            self::$input = $input;
        }

        return new self(self::$input, self::$result && !!utils::isNumber(self::$input));
    }

    /** 验证是平路为Email
     * @param null $input
     * @return verify
     */
    public static function isEmail($input = null): verify
    {
        if (func_num_args() > 0) {
            self::$input = $input;
        }

        return new self(self::$input, self::$result && !!utils::isEmail(self::$input));
    }

    /** 验证是否为Url
     * @param null $input
     * @return verify
     */
    public static function isUrl($input = null): verify
    {
        if (func_num_args() > 0) {
            self::$input = $input;
        }

        return new self(self::$input, self::$result && !!utils::isUrl(self::$input));
    }

    /** 验证是否为Ip
     * @param null $input
     * @return verify
     */
    public static function isIp($input = null): verify
    {
        if (func_num_args() > 0) {
            self::$input = $input;
        }

        return new self(self::$input, self::$result && !!utils::isIp(self::$input));
    }

    /** 验证是否为Mac
     * @param null $input
     * @return verify
     */
    public static function isMac($input = null): verify
    {
        if (func_num_args() > 0) {
            self::$input = $input;
        }

        return new self(self::$input, self::$result && !!utils::isMac(self::$input));
    }

    /** 验证是否为手机号
     * @param mixed $input
     * @return verify
     */
    public static function isMobile(mixed $input = null): verify
    {
        if (func_num_args() > 0) {
            self::$input = $input;
        }

        return new self(self::$input, self::$result && !!utils::isMobile(self::$input));
    }

    /** 验证是否少于$arg（是否 < $arg）
     * @param mixed $arg
     * @param null $input
     * @return verify
     */
    public static function less(mixed $arg, $input = null): verify
    {
        if (func_num_args() > 1) {
            self::$input = $input;
        }

        return new self(self::$input, match (true) {
            utils::isAllDate([$arg, self::$input], ["Y-m-d", "Y/m/d", "Y-m-d H:i:s", "Y/m/d H:i:s", "H:i:s"]) =>
                strtotime(self::$input) < strtotime($arg),
            utils::isAllNumber($arg, self::$input) =>
                self::$input < $arg,
            default => false
        });
    }

    /** 验证是否至少为$arg（是否 >= $arg）
     * @param mixed $arg
     * @param null $input
     * @return verify
     */
    public static function least(mixed $arg, $input = null): verify
    {
        if (func_num_args() > 1) {
            self::$input = $input;
        }

        return new self(self::$input, match (true) {
            utils::isAllDate([$arg, self::$input], ["Y-m-d", "Y/m/d", "Y-m-d H:i:s", "Y/m/d H:i:s", "H:i:s"]) =>
                strtotime(self::$input) >= strtotime($arg),
            utils::isAllNumber($arg, self::$input) =>
                self::$input >= $arg,
            default => false
        });
    }

    /** 验证是否超过$arg（是否 > $arg）
     * @param mixed $arg
     * @param null $input
     * @return verify
     */
    public static function more(mixed $arg, $input = null): verify
    {
        if (func_num_args() > 1) {
            self::$input = $input;
        }

        return new self(self::$input, match (true) {
            utils::isAllDate([$arg, self::$input], ["Y-m-d", "Y/m/d", "Y-m-d H:i:s", "Y/m/d H:i:s", "H:i:s"]) =>
                strtotime(self::$input) > strtotime($arg),
            utils::isAllNumber($arg, self::$input) =>
                self::$input > $arg,
            default => false
        });
    }

    /** 验证是否最多为$arg（是否 <= $arg）
     * @param      $arg
     * @param null $input
     * @return verify
     */
    public static function most($arg, $input = null): verify
    {
        if (func_num_args() > 1) {
            self::$input = $input;
        }

        return new self(self::$input, match (true) {
            utils::isAllDate([$arg, self::$input], ["Y-m-d", "Y/m/d", "Y-m-d H:i:s", "Y/m/d H:i:s", "H:i:s"]) =>
                strtotime(self::$input) <= strtotime($arg),
            utils::isAllNumber($arg, self::$input) =>
                self::$input <= $arg,
            default => false
        });
    }

    /** 验证指定日期或数值是否在某个$start与$end范围内
     * @param      $start
     * @param      $end
     * @param null $input
     * @return verify
     */
    public static function between($start, $end, $input = null): verify
    {
        if (func_num_args() > 2) {
            self::$input = $input;
        }

        return new self(self::$input, self::$result
            && match (true) {
                !!utils::isAllDate([$start, $end, self::$input]) =>
                    ($ts = strtotime($start)) <= ($tc = strtotime(self::$input))
                    && ($te = strtotime($end)) >= $tc
                    || $ts >= $tc && ($te ?? strtotime($end)) <= $tc,
                !!utils::isAllInt($start, $end, self::$input)
                || !!utils::isAllNumber($start, $end, self::$input) =>
                    $start <= self::$input
                    && $end >= self::$input
                    || $start >= self::$input
                    && $end <= self::$input,
                default => false
            });
    }

    /** 检查指定字符串的长度是否不超过$len
     * @param string|float $input
     * @param float $maxLen
     * @return verify
     */
    public static function len(string|float $input, float $maxLen = 0): verify
    {
        switch (func_num_args()) {
            case 1:
                if (utils::isNumber($input)) {
                    $maxLen = $input;
                } else {
                    self::$input = $input;
                }
                break;
            case 2:
                self::$input = $input;
                break;
        }

        return new self(
            self::$input,
            self::$result
            && ($maxLen == 0
                || match (true) {
                    is_string(self::$input) => strlen(self::$input) <= $maxLen,
                    !!utils::isNumber(self::$input) => self::$input <= $maxLen,
                    default => false
                }));
    }
}
